package com.ofhb.webapp.client.ui.grid;

import java.util.List;

import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.ofhb.webapp.client.ui.grid.events.PageEmptyEvent;
import com.ofhb.webapp.client.ui.grid.events.PageEmptyEventHandler;
import com.ofhb.webapp.client.ui.grid.events.RowDeleteEvent;
import com.ofhb.webapp.client.ui.grid.events.RowDeleteEventHandler;
import com.ofhb.webapp.client.utils.EventUtil;
import com.ofhb.webapp.shared.resources.ImgResources;

public class GridView extends VerticalPanel{
	private GridDataTable ftData;
	private FlexTable ftHeader;

	private int pageSize = 10;
	private boolean paging = false;
	private int currentPage = 0;
	private int totalPages = 0;
	private int totalRecords = 0;
	private Label lblPagingStatus = new Label();
	
	private GridData gridData = null;
	
	private int currentSortColumn = -1;
	private String currentSortType = null;

	final Image imgSortUp = new Image(ImgResources.INSTANCE.arrowUp());
	final Image imgSortDown = new Image(ImgResources.INSTANCE.arrowDown());
	private FlexTable ftPagingBar = null;

	public GridView() {
		setSize("", "");

		ftHeader = new FlexTable();
		ftHeader.setStyleName("app-ft-header");
		add(ftHeader);

		ftData = new GridDataTable();
		ftData.setStyleName("app-ft-border-collapse");
		add(ftData);
	}

	public void render() {
		
		List<GridHeaderCell> headerRow = gridData.getGridHeaderRow();

		int column = 0;
		for (GridHeaderCell gridHeaderCell : headerRow) {
			if(gridHeaderCell.getType() != GridDataType.ID) {
				final int col = column;
	
				final FlexTable ftHeaderCell = new FlexTable();
				ftHeaderCell.setHeight("22px");
				ftHeaderCell.getElement().setAttribute("test", "test");
				final Label lblColumn = new Label(gridHeaderCell.getDisplayName());
				lblColumn.setWordWrap(false);
				lblColumn.getElement().getStyle().setFontSize(1.1, Unit.EM);
				ftHeaderCell.setWidth(gridHeaderCell.getLength() + "px");
				ftHeaderCell.getElement().getStyle().setMargin(2, Unit.PX);
				ftHeaderCell.setWidget(0, 0, lblColumn);
	
				if (currentSortColumn == col) {
					if (currentSortType == null) {
						ftHeaderCell.setWidget(0, 1, imgSortDown);
					} else if (currentSortType.trim().equalsIgnoreCase("asc")) {
						ftHeaderCell.setWidget(0, 1, imgSortUp);
					} else if (currentSortType.trim().equalsIgnoreCase("desc")) {
						ftHeaderCell.setWidget(0, 1, imgSortDown);
					}
					ftHeaderCell.getCellFormatter().setAlignment(0, 1, ALIGN_LEFT, ALIGN_BOTTOM);
				}
				ftHeaderCell.getCellFormatter().setAlignment(0, 0, ALIGN_LEFT, ALIGN_TOP);
				ftHeader.setWidget(0, column, ftHeaderCell);
				ftHeader.getCellFormatter().setStyleName(0, column, "app-ft-header-cell");
				lblColumn.addClickHandler(new ClickHandler() {
					@Override
					public void onClick(ClickEvent event) {
						if (currentSortColumn != col) {
							currentSortType = null;
						}
	
						currentSortColumn = col;
						if (currentSortType != null) {
							if (currentSortType.equalsIgnoreCase("asc")) {
								currentSortType = "desc";
							} else if (currentSortType.equalsIgnoreCase("desc")) {
								currentSortType = "asc";
							}
						} else {
							currentSortType = "asc";
						}
						gridData.sort(col, currentSortType);
						render();
					}
				});
				column++;
			}
		}

		if (paging) {
			ftData.setData(getPageRecords(currentPage));
		} else {
			ftData.setData(gridData);
		}
		updatePagingStatus();
	}

	public GridData getPageRecords(int pageNumber){

		int from = pageNumber * pageSize;
		int to = from + pageSize;
		if(to > totalRecords) {
			to = totalRecords;
		}
		GridData pagingGridData = new GridData();
		pagingGridData.setHeaderRows(gridData.getGridHeaderRow());
		pagingGridData.setRows(gridData.getGridRows().subList(from, to));
		
		return pagingGridData;
	}

	public void setGridData(GridData gridData) {
		this.gridData = gridData;
		totalRecords = gridData.getGridRows().size();
		
		if(totalRecords <= 0 || totalRecords < pageSize + 1){
			setPaging(false);
		}
		
		totalPages = totalRecords / pageSize;
		if(totalRecords % pageSize == 0) {
			totalPages = totalPages -1;
		}
		
		attachHandler();
	}
	
	private void attachHandler() {
		
		EventUtil.EVENT_BUS.addHandler(RowDeleteEvent.TYPE, new RowDeleteEventHandler() {
			
			@Override
			public void onRowDeleteEvent(RowDeleteEvent rowDeleteEvent) {
				
				int index = currentPage * pageSize + rowDeleteEvent.getSelectedRow();
				System.out.println("Removing row index : " + index);
				gridData.getGridRows().remove(index);
				
				totalRecords = gridData.getGridRows().size();
				if(totalRecords <= 0 || totalRecords < pageSize  + 1) {
					setPaging(false);
				} 
					
				totalPages = totalRecords / pageSize;
				if(totalRecords % pageSize == 0) {
					totalPages = totalPages -1;
				}
				render();
			}
			
		});
		
		EventUtil.EVENT_BUS.addHandler(PageEmptyEvent.TYPE, new PageEmptyEventHandler() {
			
			@Override
			public void onPageEmptyEvent(PageEmptyEvent pageEmptyEvent) {
				
				totalRecords = gridData.getGridRows().size();
				if(totalRecords <= 0 || totalRecords < pageSize  + 1) {
					setPaging(false);
				} 
				totalPages = totalRecords / pageSize;
				if(totalRecords % pageSize == 0) {
					totalPages = totalPages -1;
				}
				
				if(currentPage>0) {
					currentPage--;
				}
				ftData.setData(getPageRecords(currentPage));
				updatePagingStatus();
			}
		});
	}

	protected FlexTable getFtData() {
		return ftData;
	}

	protected FlexTable getFtHeader() {
		return ftHeader;
	}

	public boolean isPaging() {
		return paging;
	}

	public void setPaging(boolean paging) {
		if (paging) {
			add(getFtPagingBar());
		} else {
			getFtPagingBar().setVisible(false);
		}
		this.paging = paging;
	}

	protected FlexTable getFtPagingBar() {
		
		if(ftPagingBar == null) {
			ftPagingBar = new FlexTable();
			ftPagingBar.setWidth("100%");
			ftPagingBar.setStyleName("app-nav-bar");
			HorizontalPanel hpPagingButtons = new HorizontalPanel();
			hpPagingButtons.setSpacing(5);
			ftPagingBar.setWidget(0, 0, hpPagingButtons);

			Button btnFirst = new Button("<<");
			btnFirst.setWidth("50px");
			hpPagingButtons.add(btnFirst);
			btnFirst.addClickHandler(new ClickHandler() {
				
				@Override
				public void onClick(ClickEvent event) {
					currentPage = 0;
					ftData.setData(getPageRecords(currentPage));
					updatePagingStatus();
				}
			});
			
			Button btnPrev = new Button("<");
			btnPrev.setWidth("50px");
			hpPagingButtons.add(btnPrev);
			btnPrev.addClickHandler(new ClickHandler() {
				
				@Override
				public void onClick(ClickEvent event) {
					if(currentPage>0) {
						currentPage--;
					}
					ftData.setData(getPageRecords(currentPage));
					updatePagingStatus();
				}
			});

			hpPagingButtons.add(lblPagingStatus);
			
			Button btnNext = new Button(">");
			hpPagingButtons.add(btnNext);
			btnNext.setWidth("50px");
			btnNext.addClickHandler(new ClickHandler() {
				
				@Override
				public void onClick(ClickEvent event) {
					if(currentPage < totalPages) {
						currentPage++;
					}
					ftData.setData(getPageRecords(currentPage));
					updatePagingStatus();
				}
			});

			Button btnLast = new Button(">>");
			hpPagingButtons.add(btnLast);
			btnLast.setWidth("50px");
			btnLast.addClickHandler(new ClickHandler() {
				
				@Override
				public void onClick(ClickEvent event) {
					currentPage = totalPages;
					ftData.setData(getPageRecords(currentPage));
					updatePagingStatus();
				}
			});

			ftPagingBar.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_RIGHT);
			ftPagingBar.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_MIDDLE);
			updatePagingStatus();
		}
		return ftPagingBar;
	}
	
	private void updatePagingStatus() {
		lblPagingStatus.getElement().getStyle().setFontSize(1.4, Unit.EM);
		lblPagingStatus.setWidth("75px");
		lblPagingStatus.setHorizontalAlignment(ALIGN_CENTER);
		lblPagingStatus.setText((currentPage+1) + " / " + (totalPages+1));
	}
}
